<template>
  <div class="user-edit-container">
    <!-- Header 区域 -->
    <van-nav-bar
      title="编辑资料"
      left-arrow
      @click-left="$router.back()"
      fixed
    />

    <!-- 用户资料 -->
    <van-cell-group class="action-card">
      <!--
        1. 点击头像区域唤起本地选择框
           input type = file
           核心：点击一个普通的img 但是效果上相当于点击了 input框
           解决方案: 准备一个隐藏状态的类型为file的input框 不显示 但是可以借助它唤起本地文件的能力

        2. 选择好本地图片之后 点击选择框的确定 自动进行上传操作
           1. 拿到图片对象：选择确定一张图片之后 会自动触发input的change事件，在事件回调中通过事件对象e
           拿到当前选择的图片对象
           2. 调用上传接口

        3. 上传成功之后需要新头像替换老头像进行显示

        整个流程:
          1. 普通的标签并不具备唤起本地文件选择的能力 所以准备了一个类型为file的input框 目的是为了借助它唤起文件选择的能力
          2. 虽然点击的是普通的标签 但是实际上触发的是 input框的click方法 模拟点击调用
          3. input被点击之后唤起本地文件选择 点击确定之后 触发了input change事件 目的拿到file对象 [e.target.files[0]]
          4. 通过原生的FormData实例化一个formData对象出来 调用append方法按照后端接口的要求 准备参数
          5. 把formData参数放到请求体  axios-data参数的位置 自动知道你要进行上传了 自动修改contentType
       -->
      <van-cell title="头像" is-link center>
        <template #default>
          <van-image @click="choseImg" class="avatar" :src="user.photo" />
          <input
            type="file"
            style="display: none"
            ref="input"
            @change="inputChange"
          />
        </template>
      </van-cell>
      <!--
        1. 点击打开弹框 弹框准备一个可以输入的文本框
        2. 回填数据并实现自动聚焦功能
        3. 点击确定按钮调用接口完成更新 替换老的name
       -->
      <van-cell title="用户名" :value="user.name" is-link @click="updateName" />
      <van-cell
        title="出生日期"
        :value="user.birthday"
        is-link
        @click="updateBirthday"
      />
    </van-cell-group>
    <!-- 更新name弹框 -->
    <van-dialog
      v-model="showNameDialog"
      title="修改名称"
      show-cancel-button
      @confirm="confirmUpdateName"
    >
      <van-field
        ref="filedInstance"
        v-model="userName"
        label="用户名"
        placeholder="请输入用户名"
      />
    </van-dialog>
    <!-- 更新生日 -->
    <van-popup
      v-model="showBirthday"
      round
      position="bottom"
      :style="{ height: '30%' }"
    >
      <van-datetime-picker
        v-model="currentDate"
        type="date"
        title="选择年月日"
        @confirm="confirmUpdateBirthday"
      />
    </van-popup>
  </div>
</template>

<script>
import { getUser, uploadImg, updateProfile } from '@/api'
import dayjs from 'dayjs'
export default {
  name: 'UserEdit',
  data () {
    return {
      user: {},
      showNameDialog: false,
      userName: '',
      showBirthday: false,
      currentDate: new Date()
    }
  },
  mounted () {
    this.fetchUser()
  },
  methods: {
    async fetchUser () {
      const res = await getUser()
      this.user = res.data
    },
    choseImg () {
      // 模拟点击input框 相当于通过方法执行的方式 模拟鼠标点击事件
      this.$refs.input.click()
    },
    async inputChange (e) {
      console.log(e.target.files[0])
      const file = e.target.files[0]
      if (!file) {
        return false
      }
      const formData = new FormData()
      formData.append('photo', file)
      const res = await uploadImg(formData)
      // 替换老头像 乐观更新
      this.user.photo = res.data.photo
    },
    updateName () {
      this.showNameDialog = true
      // 回显数据
      this.userName = this.user.name
      // 自动聚焦 - focus()
      // 获取实例 - 实例的 focus

      // 注意: 输入框的渲染 需要等到外层弹框组件渲染出来之后 才能得到实例
      // 当我们把决定弹框是否显示的属性设置为true时，弹框的显示渲染是异步的，包裹在了一个微任务中
      // 解决办法: 把获取实例的方法也放到一个异步任务中 nextTick -> promise.then()

      // this.$nextTick(() => {
      //   console.log(this.$refs.filedInstance)
      //   this.$refs.filedInstance.focus()
      // })

      // 如果setTimeout的第二个参数不是0 大概率用错了
      // setTimeout(() => {
      //   this.$refs.filedInstance.focus()
      // }, 0)

      Promise.resolve().then(() => {
        this.$refs.filedInstance.focus()
      })
    },
    async confirmUpdateName () {
      // 1. 先把本来的用户信息对象展开
      // 2. 替换要修改的name属性
      await updateProfile({
        ...this.user,
        name: this.userName
      })
      this.user.name = this.userName
    },
    updateBirthday () {
      this.showBirthday = true
      // 使用user.birthday 初始化 双向绑定的curentDate
      this.currentDate = new Date(this.user.birthday)
    },
    async confirmUpdateBirthday () {
      // 提交之前先把标准的组件产出的时间格式转化成为后端要求的string 2022-08-26
      const formatTime = dayjs(this.currentDate).format('YYYY-MM-DD')
      await updateProfile({
        ...this.user,
        birthday: formatTime
      })
      // 更新本地显示
      this.user.birthday = formatTime
      // 关闭弹框
      this.showBirthday = false
    }
  }
}
</script>

<style lang="less" scoped>
.user-edit-container {
  padding-top: 46px;
  .avatar {
    width: 50px;
    height: 50px;
  }
}
</style>
